import json
import matplotlib.pyplot as plt
import numpy as np
from matplotlib.patches import Polygon
import matplotlib.patches as patches

def load_annotation_file(file_path):
    """加载标注文件"""
    with open(file_path, 'r', encoding='utf-8') as f:
        return json.load(f)

def analyze_bbox_order(annotation_data, title):
    """分析bbox中p1p2p3p4点的顺序"""
    print(f"\n=== {title} ===")
    print(f"表格类型: {annotation_data.get('type', 'Unknown')}")
    print(f"质量: {annotation_data.get('quality', 'Unknown')}")
    print(f"单元格数量: {len(annotation_data['cells'])}")
    
    # 分析每个单元格的bbox点顺序
    bbox_analysis = []
    for i, cell in enumerate(annotation_data['cells']):
        if cell['bbox']:
            bbox = cell['bbox']
            p1, p2, p3, p4 = bbox['p1'], bbox['p2'], bbox['p3'], bbox['p4']
            
            # 计算点的相对位置关系
            analysis = {
                'cell_ind': cell['cell_ind'],
                'content': cell['content'][0]['text'] if cell['content'] else '',
                'p1': p1, 'p2': p2, 'p3': p3, 'p4': p4,
                'bbox_pattern': analyze_point_pattern(p1, p2, p3, p4),
                'corner_positions': get_corner_positions(p1, p2, p3, p4)
            }
            bbox_analysis.append(analysis)
            
            if i < 5:  # 只显示前5个单元格的详细信息
                print(f"\n单元格 {cell['cell_ind']} ('{analysis['content'][:10]}...'):")
                print(f"  p1: {p1} -> {analysis['corner_positions']['p1']}")
                print(f"  p2: {p2} -> {analysis['corner_positions']['p2']}")
                print(f"  p3: {p3} -> {analysis['corner_positions']['p3']}")
                print(f"  p4: {p4} -> {analysis['corner_positions']['p4']}")
                print(f"  模式: {analysis['bbox_pattern']}")
    
    return bbox_analysis

def get_corner_positions(p1, p2, p3, p4):
    """确定每个点在矩形中的位置（左上、右上、左下、右下）"""
    points = {'p1': p1, 'p2': p2, 'p3': p3, 'p4': p4}
    
    # 找到x和y的最值
    x_coords = [p[0] for p in [p1, p2, p3, p4]]
    y_coords = [p[1] for p in [p1, p2, p3, p4]]
    
    min_x, max_x = min(x_coords), max(x_coords)
    min_y, max_y = min(y_coords), max(y_coords)
    
    # 确定每个点的位置
    positions = {}
    for name, point in points.items():
        x, y = point
        if abs(x - min_x) < abs(x - max_x):  # 更接近左边
            if abs(y - min_y) < abs(y - max_y):  # 更接近上边
                positions[name] = "左上角"
            else:  # 更接近下边
                positions[name] = "左下角"
        else:  # 更接近右边
            if abs(y - min_y) < abs(y - max_y):  # 更接近上边
                positions[name] = "右上角"
            else:  # 更接近下边
                positions[name] = "右下角"
    
    return positions

def analyze_point_pattern(p1, p2, p3, p4):
    """分析四个点的排列模式"""
    # 检查是否是顺时针或逆时针
    if is_clockwise_order(p1, p2, p3, p4):
        direction = "顺时针"
    else:
        direction = "逆时针"
    
    return direction

def is_clockwise_order(p1, p2, p3, p4):
    """判断四个点是否按顺时针排列"""
    # 使用叉积判断方向
    def cross_product(o, a, b):
        return (a[0] - o[0]) * (b[1] - o[1]) - (a[1] - o[1]) * (b[0] - o[0])
    
    # 计算连续三个点的叉积
    cross1 = cross_product(p1, p2, p3)
    cross2 = cross_product(p2, p3, p4)
    cross3 = cross_product(p3, p4, p1)
    cross4 = cross_product(p4, p1, p2)
    
    # 如果所有叉积都是负数，则是顺时针
    return all(c < 0 for c in [cross1, cross2, cross3, cross4])

def visualize_bbox_comparison(data1, data2, title1, title2):
    """可视化两个文件的bbox对比"""
    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(20, 10))
    
    # 设置中文字体
    plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS', 'DejaVu Sans']
    plt.rcParams['axes.unicode_minus'] = False
    
    # 可视化第一个文件
    visualize_single_file(ax1, data1, title1)
    
    # 可视化第二个文件
    visualize_single_file(ax2, data2, title2)
    
    plt.tight_layout()
    plt.savefig('bbox_comparison.png', dpi=300, bbox_inches='tight')
    plt.show()

def visualize_single_file(ax, bbox_analysis, title):
    """可视化单个文件的bbox"""
    ax.set_title(title, fontsize=14, fontweight='bold')
    
    colors = plt.cm.Set3(np.linspace(0, 1, len(bbox_analysis)))
    
    for i, analysis in enumerate(bbox_analysis[:8]):  # 只显示前8个单元格
        p1, p2, p3, p4 = analysis['p1'], analysis['p2'], analysis['p3'], analysis['p4']
        
        # 绘制矩形
        polygon = Polygon([p1, p2, p3, p4], alpha=0.3, color=colors[i], edgecolor='black', linewidth=1)
        ax.add_patch(polygon)
        
        # 标记点的顺序
        points = [p1, p2, p3, p4]
        labels = ['p1', 'p2', 'p3', 'p4']
        point_colors = ['red', 'blue', 'green', 'orange']
        
        for j, (point, label, color) in enumerate(zip(points, labels, point_colors)):
            ax.plot(point[0], point[1], 'o', color=color, markersize=10)
            ax.annotate(f'{label}', (point[0], point[1]), xytext=(8, 8), 
                       textcoords='offset points', fontsize=10, color=color, fontweight='bold',
                       bbox=dict(boxstyle="round,pad=0.2", facecolor='white', alpha=0.8))
        
        # 绘制连接线显示顺序
        for j in range(4):
            start = points[j]
            end = points[(j + 1) % 4]
            ax.annotate('', xy=end, xytext=start,
                       arrowprops=dict(arrowstyle='->', color='black', alpha=0.7, lw=2))
        
        # 添加单元格内容和模式标签
        center_x = sum(p[0] for p in points) / 4
        center_y = sum(p[1] for p in points) / 4
        content = analysis['content'][:3] + '...' if len(analysis['content']) > 3 else analysis['content']
        pattern = analysis['bbox_pattern']
        
        ax.text(center_x, center_y, f"{content}\n({pattern})", ha='center', va='center', 
               fontsize=8, bbox=dict(boxstyle="round,pad=0.3", facecolor='yellow', alpha=0.7))
    
    ax.set_aspect('equal')
    ax.grid(True, alpha=0.3)
    ax.invert_yaxis()  # 图像坐标系y轴向下

def compare_patterns(analysis1, analysis2):
    """比较两个文件的模式差异"""
    print("\n=== 模式对比分析 ===")
    
    # 统计模式分布
    patterns1 = [a['bbox_pattern'] for a in analysis1]
    patterns2 = [a['bbox_pattern'] for a in analysis2]
    
    print(f"文件1模式分布:")
    for pattern in set(patterns1):
        count = patterns1.count(pattern)
        print(f"  {pattern}: {count}个单元格")
    
    print(f"\n文件2模式分布:")
    for pattern in set(patterns2):
        count = patterns2.count(pattern)
        print(f"  {pattern}: {count}个单元格")
    
    # 分析具体差异
    print(f"\n=== 具体点位置分析 ===")
    print("文件1前5个单元格的点位置:")
    for i, analysis in enumerate(analysis1[:5]):
        print(f"单元格{i}: {analysis['corner_positions']}")
    
    print("\n文件2前5个单元格的点位置:")
    for i, analysis in enumerate(analysis2[:5]):
        print(f"单元格{i}: {analysis['corner_positions']}")

def create_detailed_analysis():
    """创建详细的分析报告"""
    print("\n" + "="*80)
    print("详细分析报告：两个表格标注文件的bbox点顺序差异")
    print("="*80)

    print("\n【关键发现】")
    print("1. 文件1使用顺时针点顺序：p1(右上) -> p2(左上) -> p3(左下) -> p4(右下)")
    print("2. 文件2使用逆时针点顺序：p1(左上) -> p2(右上) -> p3(右下) -> p4(左下)")
    print("3. 这是导致文件1质量为'待校准'的主要原因")

    print("\n【标准格式分析】")
    print("根据文件2（质量：合格）的格式，标准的bbox点定义应该是：")
    print("- p1: 左上角 (Top-Left)")
    print("- p2: 右上角 (Top-Right)")
    print("- p3: 右下角 (Bottom-Right)")
    print("- p4: 左下角 (Bottom-Left)")
    print("- 顺序: 逆时针方向")

    print("\n【文件1的问题】")
    print("文件1的点定义顺序错误：")
    print("- p1: 右上角 (应该是左上角)")
    print("- p2: 左上角 (应该是右上角)")
    print("- p3: 左下角 (应该是右下角)")
    print("- p4: 右下角 (应该是左下角)")
    print("- 顺序: 顺时针方向 (应该是逆时针)")

    print("\n【影响分析】")
    print("这种点顺序错误会导致：")
    print("1. 表格识别算法无法正确解析单元格边界")
    print("2. 单元格内容定位出现偏差")
    print("3. 表格结构分析失败")
    print("4. 下游任务（如OCR、表格理解）性能下降")

def main():
    # 加载三个文件：原始文件、修复后文件、参考文件
    file1 = "1617292400882827329823143747584_0_table_annotation.json"
    file1_fixed = "fixed_1617292400882827329823143747584_0_table_annotation.json"
    file2 = "_4g_ndt1_yf_table_annotation.json"

    data1 = load_annotation_file(file1)
    data1_fixed = load_annotation_file(file1_fixed)
    data2 = load_annotation_file(file2)

    # 分析bbox顺序
    analysis1 = analyze_bbox_order(data1, "原始文件: 1617292400882827329823143747584_0")
    analysis1_fixed = analyze_bbox_order(data1_fixed, "修复后文件: fixed_1617292400882827329823143747584_0")
    analysis2 = analyze_bbox_order(data2, "参考文件: _4g_ndt1_yf")

    # 比较模式
    print("\n=== 原始文件 vs 参考文件 ===")
    compare_patterns(analysis1, analysis2)

    print("\n=== 修复后文件 vs 参考文件 ===")
    compare_patterns(analysis1_fixed, analysis2)

    # 创建详细分析
    create_detailed_analysis()

    # 可视化对比
    try:
        # 对比修复前后
        visualize_bbox_comparison(analysis1, analysis1_fixed,
                                "原始文件 (顺时针-错误)",
                                "修复后文件 (逆时针-正确)")
        print("\n修复前后对比图表已保存为 'bbox_comparison.png'")

        # 对比修复后与参考文件
        import matplotlib.pyplot as plt
        fig2, (ax1, ax2) = plt.subplots(1, 2, figsize=(20, 10))
        plt.rcParams['font.sans-serif'] = ['SimHei', 'Arial Unicode MS', 'DejaVu Sans']
        plt.rcParams['axes.unicode_minus'] = False

        visualize_single_file(ax1, analysis1_fixed, "修复后文件")
        visualize_single_file(ax2, analysis2, "参考文件")

        plt.tight_layout()
        plt.savefig('fixed_vs_reference.png', dpi=300, bbox_inches='tight')
        print("修复后与参考文件对比图表已保存为 'fixed_vs_reference.png'")
        plt.close(fig2)

    except Exception as e:
        print(f"\n可视化生成失败: {e}")
        print("但分析结果已完成，请查看上述文本分析。")

    # 总结差异
    print("\n=== 修复建议 ===")
    print("要修复文件1，需要重新定义bbox点顺序：")
    print("1. 将当前的p1(右上)改为p2")
    print("2. 将当前的p2(左上)改为p1")
    print("3. 将当前的p3(左下)改为p4")
    print("4. 将当前的p4(右下)改为p3")
    print("5. 确保所有单元格都遵循：p1(左上)->p2(右上)->p3(右下)->p4(左下)的逆时针顺序")

if __name__ == "__main__":
    main()
